/* Copyright (c) 2004-2008, Andriy Nikolov
 * All rights reserved.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package org.processmining.email;

import java.awt.Point;
import java.awt.Graphics;

/**
 * <p>Draws an arc in all diagrams in the standalone version</p>
 *
 * @author Andriy Nikolov
 * @version 1.0
 */
public class DiagramArc {
  DiagramNode nodeFrom, nodeTo;
  double weight;
  Point offsetFrom, offsetTo;
  Point absoluteFrom, absoluteTo;
  Point arrowhead;
  Point pointArrowLeft;
  Point pointArrowRight;
  Point pointCenter;
  Point pointOneThird;

  public DiagramArc() {
    offsetFrom = new Point(0, 0);
    offsetTo = new Point(0, 0);
  }

  public void setFrom(DiagramNode from) {
    nodeFrom = from;
  }

  public void setTo(DiagramNode to) {
    nodeTo = to;
  }

  public DiagramNode getFrom() {
    return nodeFrom;
  }

  public DiagramNode getTo() {
    return nodeTo;
  }

  public void setWeight(double weight) {
    this.weight = weight;
  }

  public double getWeight() {
    return weight;
  }

  public Point getOffsetFrom() {
    return offsetFrom;
  }

  public void setOffsetFrom(int x, int y) {
    offsetFrom = new Point(x, y);
  }

  public void setOffsetFrom(Point point) {
    offsetFrom = new Point(point);
  }

  public Point getOffsetTo() {
    return offsetTo;
  }

  public void setOffsetTo(int x, int y) {
    offsetTo = new Point(x, y);
  }

  public void setOffsetTo(Point point) {
    offsetTo = new Point(point);
  }

  public void paint(Graphics g) {
    // Draw line
    calculateAbsolutes();
    g.drawLine(absoluteFrom.x, absoluteFrom.y, absoluteTo.x, absoluteTo.y);
    // Draw arrow
    getArrowheadPoints();
    g.drawLine(arrowhead.x, arrowhead.y, pointArrowLeft.x, pointArrowLeft.y);
    g.drawLine(arrowhead.x, arrowhead.y, pointArrowRight.x, pointArrowRight.y);
    // Draw text
//    g.drawString(Double.toString(weight), pointCenter.x, pointCenter.y);
  }

  private void getArrowheadPoints() {
    arrowhead = new Point();
    pointArrowLeft = new Point();
    pointArrowRight = new Point();
    pointCenter = new Point();
    //    pointOneThird = new Point();
    double length, delta;
    Point arrowback = new Point();

    length = Math.sqrt(Math.pow( (absoluteTo.y - absoluteFrom.y), 2) +
                       Math.pow( (absoluteTo.x - absoluteFrom.x), 2));
    if (absoluteTo.y != absoluteFrom.y) {
      delta = (absoluteTo.x - absoluteFrom.x) / length;
      arrowhead.x = new Double(absoluteTo.x -
                               delta * (DiagramNode.NODE_WIDTH / 2)).intValue();
      arrowback.x = new Double(absoluteTo.x -
                               delta *
                               (DiagramNode.NODE_WIDTH / 2 +
                                5 * DiagramNode.scale)).intValue();
    }
    else {
      arrowhead.x = (absoluteTo.x >= absoluteFrom.x) ?
          (absoluteTo.x - DiagramNode.NODE_WIDTH * DiagramNode.scale / 2) :
          (absoluteTo.x + DiagramNode.NODE_WIDTH * DiagramNode.scale / 2);
      arrowback.x = (absoluteTo.x >= absoluteFrom.x) ?
          (arrowhead.x - 5 * DiagramNode.scale) :
          (arrowhead.x + DiagramNode.scale * 5);
    }
    if (absoluteTo.x != absoluteFrom.x) {
      delta = (absoluteTo.y - absoluteFrom.y) / length;
      arrowhead.y = new Double(absoluteTo.y -
                               delta * (DiagramNode.NODE_WIDTH / 2)).intValue();
      arrowback.y = new Double(absoluteTo.y -
                               delta *
                               (DiagramNode.NODE_WIDTH / 2 +
                                5 * DiagramNode.scale)).intValue();
    }
    else {
      arrowhead.y = (absoluteTo.y >= absoluteFrom.y) ?
          (absoluteTo.y - DiagramNode.NODE_WIDTH / 2) :
          (absoluteTo.y + DiagramNode.NODE_WIDTH / 2);
      arrowback.y = (absoluteTo.y >= absoluteFrom.y) ?
          (arrowhead.y - 5 * DiagramNode.scale) :
          (arrowhead.y + 5 * DiagramNode.scale);
    }
    pointArrowRight.x = arrowback.x - (arrowhead.y - arrowback.y);
    pointArrowRight.y = arrowback.y + (arrowhead.x - arrowback.x);
    pointArrowLeft.x = arrowback.x + (arrowhead.y - arrowback.y);
    pointArrowLeft.y = arrowback.y - (arrowhead.x - arrowback.x);
    pointCenter.x = (absoluteTo.x + absoluteFrom.x) / 2;
    pointCenter.y = (absoluteTo.y + absoluteFrom.y) / 2;
    //    pointOneThird.x = (absoluteTo.x+absoluteFrom.x)/3;
    //    pointOneThird.x = (absoluteTo.y+absoluteFrom.y)/3;
  }

  private void calculateAbsolutes() {
    absoluteFrom = new Point();
    absoluteTo = new Point();
    absoluteFrom.x = nodeFrom.getCenter().x + offsetFrom.x;
    absoluteFrom.y = nodeFrom.getCenter().y + offsetFrom.y;
    absoluteTo.x = nodeTo.getCenter().x + offsetTo.x;
    absoluteTo.y = nodeTo.getCenter().y + offsetTo.y;
  }
}
